#pragma once
#include <iostream>
#include <memory>
#include <type_traits>

class MString
{
	friend std::ostream &operator<<(std::ostream &o, const MString &str);
	friend bool operator==(const MString &str1, const MString &str2);
	friend bool operator<(const MString &str1, const MString &str2);
	friend MString operator+(const MString &str1, const MString &str2);
public:
	template<typename Val_Type, bool is_reverse = false>
	class iterator_base;//声明为MString的嵌套类
	template<typename Val_Type, bool is_reverse>
	friend class iterator_base;

	typedef char value_type;

	typedef iterator_base<char> iterator;
	typedef iterator_base<const char> const_iterator;
	typedef iterator_base<char, true> reverse_iterator;
	typedef iterator_base<const char, true> const_reverse_iterator;
public:
	MString(size_t n);
	MString(const char* str = nullptr);
	MString(const MString &other);
	MString(MString &&other);
	virtual ~MString();
	MString &operator=(const MString &other);
	MString &operator=(MString &&other);
	MString &operator+=(const MString &other);
	size_t size() const;//当前字符串长度,不包含尾部空字符
	size_t capacity() const;//当前内存容量
	bool empty() const;
	void clear();
	const char *c_str() const;
	iterator insert(const_iterator i, value_type v);//使用insert_iterator()时会被调用

	//iterator:
	iterator begin();
	const_iterator begin() const;
	iterator end();
	const_iterator end() const;
	const_iterator cbegin() const;
	const_iterator cend() const;
	reverse_iterator rbegin();
	const_reverse_iterator rbegin() const;
	reverse_iterator rend();
	const_reverse_iterator rend() const;
	const_reverse_iterator crbegin() const;
	const_reverse_iterator crend() const;
private:
	char *allocat(size_t new_cap = M_CAPACITY_STEP);
	size_t copy_str(const char *str);//拷贝，返回成功拷贝的长度.有隐患：如果字符串不是以空结尾则出问题
	void set_capacity(size_t new_cap);
	bool append(const char *str);
	bool check(const_iterator i,const char *err) const;
private:
	static size_t increase_to(size_t cur_cap, size_t new_cap);//每次都乘以2
private:
	std::unique_ptr<char[]> m_pStr;
	size_t m_capacity = 0;
	const static int M_CAPACITY_STEP = 4;//分配内存增长的初始步长
};

template<typename Val_Type, bool is_reverse>
class MString::iterator_base
{
public:
	typedef Val_Type* pointer;
	typedef Val_Type& reference;
	typedef Val_Type value_type;
	typedef std::random_access_iterator_tag iterator_category;//不知道做什么用的，不定义就编译不通过？？？？？？？？？？？？？？
	typedef long long difference_type;//代表两个迭代器之间的距离
	//typedef long long distance_type;	// retained

	template<typename Val_Type, bool is_reverse>
	friend typename MString::iterator_base<Val_Type, is_reverse>::difference_type operator-(const MString::iterator_base<Val_Type, is_reverse> &left, const MString::iterator_base<Val_Type, is_reverse> &right);

	//为了本模板不同类型互相转换时访问私有构造函数：
	template<typename Val_Type1, bool is_reverse1>
	friend class iterator_base;

	typedef iterator_base<Val_Type, is_reverse> _Myiter;
	typedef _Myiter _Unchecked_type;//使用stl算法时被调用，用于检查合法性
public:
	iterator_base(){};
	iterator_base(const iterator_base& other) : m_ptr(other.m_ptr), m_cur_pos(other.m_cur_pos){};
	iterator_base &operator=(const iterator_base &other)
	{
		if (this != &other)
		{
			m_ptr = other.m_ptr;
			m_cur_pos = other.m_cur_pos;
		}
		return *this;
	}
	virtual ~iterator_base(){};
	iterator_base &operator+=(difference_type dis)//所有+-int操作均最终调用此函数
	{
		m_cur_pos += dis * (is_reverse ? -1 : 1);
		return *this;
	};

	_Myiter& _Rechecked(_Unchecked_type _Right)
	{	// reset from unchecked iterator
		*this = _Right;
		return (*this);
	}
	//使用stl算法时被调用，用于检查合法性
	_Unchecked_type _Unchecked() const
	{	// make an unchecked iterator
		return (*this);
	}

	iterator_base& operator++()
	{
		return (*this) += 1;
	};
	iterator_base operator++(int)
	{
		iterator_base iter(*this);
		(*this) += 1;
		return iter;
	};
	iterator_base &operator-=(difference_type dis)
	{
		return (*this)+=(-1 * dis);
	};
	iterator_base &operator--()
	{
		return (*this) -= 1;
	};
	iterator_base operator--(int)
	{
		iterator_base iter(*this);
		(*this) -= 1;
		return iter;
	};
	bool operator==(const iterator_base &other) const
	{
		if (this == &other)
			return true;
		else
			return m_ptr == other.m_ptr && m_cur_pos == other.m_cur_pos;
	};
	bool operator!=(const iterator_base &other) const
	{
		return !(*this == other);
	};
	bool operator<(const iterator_base &other)
	{
		if (m_ptr != other.m_ptr)
			throw std::runtime_error("can not compare tow iterators came from different objects");
		return m_cur_pos < other.m_cur_pos;
	};
	bool operator>(const iterator_base &other)
	{
		if (m_ptr != other.m_ptr)
			throw std::runtime_error("can not compare tow iterators came from different objects");
		return !(*this<other) && (*this!=other);
	};
	bool operator>=(const iterator_base &other)
	{
		if (m_ptr != other.m_ptr)
			throw std::runtime_error("can not compare tow iterators came from different objects");
		return !(*this<other);
	};
	bool operator<=(const iterator_base &other)
	{
		if (m_ptr != other.m_ptr)
			throw std::runtime_error("can not compare tow iterators came from different objects");
		return !(*this > other);
	};
	reference operator*()
	{
		return *(m_ptr + m_cur_pos);
	};
	pointer operator->()
	{
		return m_ptr + m_cur_pos;
	};
	//从非const类型隐式转换为const类型
	operator iterator_base<typename std::add_const<Val_Type>::type, is_reverse>() const
	{
		return iterator_base<typename std::add_const<Val_Type>::type, is_reverse>(m_ptr, m_cur_pos);
	}
	//从const类型显式转换为非const类型
	explicit operator iterator_base<typename std::remove_const<Val_Type>::type, is_reverse>() const
	{
		return iterator_base<typename std::remove_const<Val_Type>::type, is_reverse>
			(const_cast<typename std::remove_const<Val_Type>::type *>(m_ptr), m_cur_pos);
	}
	//从reverse类型转换为非reverse类型
	iterator_base<Val_Type, false> base()  const
	{
		if (is_reverse)
			return iterator_base<Val_Type, false>(m_ptr, m_cur_pos + 1);
		else
			return iterator_base<Val_Type, false>(m_ptr,m_cur_pos);
	}
	static iterator_base make_begin(const MString &str)
	{
		return iterator_base(str.m_pStr.get(), is_reverse ? str.size()-1 : 0);
	};
	static iterator_base make_end(const MString &str)
	{
		return iterator_base(str.m_pStr.get(), is_reverse ? -1 : str.size());
	}
private:
	iterator_base(pointer p, difference_type pos) :m_ptr(p), m_cur_pos(pos){};
private:
	pointer m_ptr = nullptr;
	difference_type m_cur_pos = 0;
};

template<typename Val_Type, bool is_reverse>
MString::iterator_base<Val_Type, is_reverse> operator+(const MString::iterator_base<Val_Type, is_reverse> &iter, typename MString::iterator_base<Val_Type, is_reverse>::difference_type dis)
{
	MString::iterator_base<Val_Type, is_reverse> i(iter);
	return i += dis;
}

template<typename Val_Type, bool is_reverse>
MString::iterator_base<Val_Type, is_reverse> operator-(const MString::iterator_base<Val_Type, is_reverse> &iter, typename MString::iterator_base<Val_Type, is_reverse>::difference_type dis)
{
	MString::iterator_base<Val_Type, is_reverse> i(iter);
	return i -= dis;
}

template<typename Val_Type, bool is_reverse>
typename MString::iterator_base<Val_Type, is_reverse>::difference_type operator-(const MString::iterator_base<Val_Type, is_reverse> &left, const MString::iterator_base<Val_Type, is_reverse> &right)
{
	if (left.m_ptr != right.m_ptr)
		throw std::runtime_error("can not operate tow iterators came from different objects");
	return (left.m_cur_pos - right.m_cur_pos) * (is_reverse ? -1 : 1);
}
